package com.sea.listener;


import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sea.config.SerialPortManager;
import com.sea.domain.Struct;
import com.sea.struct.data.StatusData;
import com.sea.struct.data.StatusData2;
import com.sea.utils.ByteUtils;
import com.sea.utils.StrUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class SerialPortCallback {

    private static Logger logger = LoggerFactory.getLogger(SerialPortCallback.class);

    public void dataAvailable() {
        try {
            //当前监听器监听到的串口返回数据 back
            byte[] back = SerialPortManager.readSerialPortData();
            String res = StrUtils.bytesToHeString(back);
            logger.info("rev--data:" + res);

            String hostNum = res.substring(0, 2);   // 电源柜号
            String funCode = res.substring(3, 5);   // 功能码
            if (hostNum.equals("01")) {
                if (funCode.equals("03")) {
                    handleFunCode3(res, hostNum);
                } else if (funCode.equals("02")) {
                    handleFunCode2(res, hostNum);
                }
            } else if (hostNum.equals("02")) {
                if (funCode.equals("03")) {
                    handleFunCode3_(res, hostNum);
                } else if (funCode.equals("02")) {
                    handleFunCode2(res, hostNum);
                }
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    private void handleFunCode2(String msg, String hostNum) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
        List<Character> list = new ArrayList<>();
        for (int j = 6; j < 20; j++) {
            char[] chars = handleMsg(msg, j, j + 2);
            for (int i = chars.length - 1; i >= 0; i--) {
                list.add(chars[i]);
            }
            j = j + 1;
        }

        StatusData statusData = new StatusData();
        Field[] fields = statusData.getClass().getDeclaredFields();
        for (int i = 0; i < list.size() - 6; i++) { // list.size() 56 字段长度50
            fields[i].setAccessible(true);
            String attributeName = fields[i].getName(); // 获取字段名
            String methodName = attributeName.substring(0, 1).toUpperCase() + attributeName.substring(1);      //将属性名的首字母变为大写，为执行set/get方法做准备
            Method setMethod = StatusData.class.getMethod("set" + methodName, String.class);
            System.out.println(setMethod);
            setMethod.invoke(statusData, String.valueOf(list.get(i)));
        }

        ObjectMapper mapper = new ObjectMapper();
        String statusDataStr = JSONObject.toJSON(statusData).toString();
        StatusData stdata = mapper.readValue(statusDataStr, StatusData.class);
        try {
            if (hostNum.equals("01")) {
                mapper.writeValue(new File("host_1_2.json"), stdata);
                logger.info("---host_1_2文件写入成功----");
            }
            if (hostNum.equals("02")) {
                mapper.writeValue(new File("host_2_2.json"), stdata);
                logger.info("---host_2_2文件写入成功----");
            }
        } catch (IOException e) {
            logger.error("---host_#_2文件写入失败----" + e.getMessage());
        }


    }

    private void handleFunCode2_(String msg, String hostNum) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
        List<Character> list = new ArrayList<>();
        for (int j = 6; j < 20; j++) {
            char[] chars = handleMsg(msg, j, j + 2);
            for (int i = chars.length - 1; i >= 0; i--) {
                list.add(chars[i]);
            }
            j = j + 1;
        }

        StatusData2 statusData = new StatusData2();
        Field[] fields = statusData.getClass().getDeclaredFields();
        for (int i = 0; i < list.size() - 6; i++) { // list.size() 56 字段长度50
            fields[i].setAccessible(true);
            String attributeName = fields[i].getName(); // 获取字段名
            String methodName = attributeName.substring(0, 1).toUpperCase() + attributeName.substring(1);      //将属性名的首字母变为大写，为执行set/get方法做准备
            Method setMethod = StatusData.class.getMethod("set" + methodName, String.class);
            setMethod.invoke(statusData, String.valueOf(list.get(i)));
        }

        ObjectMapper mapper = new ObjectMapper();
        String statusDataStr = JSONObject.toJSON(statusData).toString();
        StatusData2 stdata = mapper.readValue(statusDataStr, StatusData2.class);
        try {
            mapper.writeValue(new File("host_2_2.json"), stdata);
            logger.info("---host_2_2文件写入成功----");
        } catch (IOException e) {
            logger.error("---host_2_2文件写入失败----" + e.getMessage());
        }
    }

    private void handleFunCode3(String res, String hostNum) throws IOException {
        // Step1 响应数据处理
        // Step1.1 hex -> stream
        byte[] bytes = StrUtils.hexStringToBytes(res);
        InputStream in = StrUtils.byte2InputStream(bytes);

        // Step1.2 stream -> byte
        ByteArrayOutputStream bs = null;
        byte[] b = new byte[1];
        while (in.read(b) != -1) {
            if (b[0] == 0x01) {
                if (bs == null) {
                    bs = new ByteArrayOutputStream();
                }
                bs.write(b);
            } else {
                if (bs != null) {
                    bs.write(b);
                }
            }

            if (bs != null) {
                byte[] bts = bs.toByteArray();
                if (bts.length > 2) {                                           // 控制业务字段长度位置,如果业务字段长度是第二位length>1,如果业务字段长度第三位length>2
                    long functionCode = ByteUtils.Long(new byte[]{bts[1]});     // 功能码
//                        System.out.println("-----功能码-----:" + functionCode);
                    if (functionCode == 3) {
//                            System.out.println(bts[2]);
                        long dataLen = ByteUtils.Long(new byte[]{bts[2]});     // 长度
//                            System.out.println("-----长度-----:" + dataLen);

                        // 读取到消息总长度就不读了
                        long totalLen = 1 + 1 + 1 + dataLen + 2; //消息总长度=从机地址（1） +功能码（1） + 数据长度 + 帧校验域（2）
                        if (bts.length == totalLen) {
                            System.out.println("-----读取完了-----");
                            Map<String, Object> handleMap = handle(bs, hostNum);
                        }
                    }
                }
            }
        }
    }


    private void handleFunCode3_(String res, String hostNum) throws IOException {
        // Step1 响应数据处理
        // Step1.1 hex -> stream
        byte[] bytes = StrUtils.hexStringToBytes(res);
        InputStream in = StrUtils.byte2InputStream(bytes);

        // Step1.2 stream -> byte
        ByteArrayOutputStream bs = null;
        byte[] b = new byte[1];
        while (in.read(b) != -1) {
            if (b[0] == 0x02) {
                if (bs == null) {
                    bs = new ByteArrayOutputStream();
                }
                bs.write(b);
            } else {
                if (bs != null) {
                    bs.write(b);
                }
            }

            if (bs != null) {
                byte[] bts = bs.toByteArray();
                if (bts.length > 2) {                                           // 控制业务字段长度位置,如果业务字段长度是第二位length>1,如果业务字段长度第三位length>2
                    long functionCode = ByteUtils.Long(new byte[]{bts[1]});     // 功能码
                    if (functionCode == 3) {
                        long dataLen = ByteUtils.Long(new byte[]{bts[2]});     // 长度
                        // 读取到消息总长度就不读了
                        long totalLen = 1 + 1 + 1 + dataLen + 2; //消息总长度=从机地址（1） +功能码（1） + 数据长度 + 帧校验域（2）
                        if (bts.length == totalLen) {
                            Map<String, Object> handleMap = handle_(bs, hostNum);
                        }
                    }
                }
            }
        }
    }

    private Map<String, Object> handle(ByteArrayOutputStream bs, String hostNum) throws IOException {
        Map<String, Object> map = new HashMap<>();
        try {
            Struct struct = new Struct();
            Map<String, Object> result = struct.parserInput(bs, hostNum);
            return result;
        } catch (Exception e) {
            return map;
        }
    }

    private Map<String, Object> handle_(ByteArrayOutputStream bs, String hostNum) throws IOException {
        Map<String, Object> map = new HashMap<>();
        try {
            Struct struct = new Struct();
            Map<String, Object> result = struct.parserInput_(bs, hostNum);
            return result;
        } catch (Exception e) {
            return map;
        }
    }

    /**
     * 00 → 0000 0000
     * 4a → 0100 1010
     */
    private static char[] handleMsg(String msg, int start, int end) {
        String s = StringUtils.deleteWhitespace(msg);
        String seg1 = s.substring(start, end);
        String binaryNumber = Integer.toBinaryString(Integer.parseInt(seg1, 16));
        String formattedNumber = String.format("%08d", Integer.parseInt(binaryNumber));
        return formattedNumber.toCharArray();
    }


}

